﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Diagnostics;
using Ict.DataAccess.Conditions;
using Ict.DataAccess.Attributes;

namespace Ict.DataAccess
{
    /// <summary>
    /// 执行数据库调用的接口，不同的数据库应有不同的实现
    /// </summary>
    public abstract class Executor : IDisposable
    {
        private static int _ConnectionCount = 0;

        private static int _ConnectionPeakCount = 0;

        private static int _ConnectionTotalCount = 0;

        /// <summary>
        /// 当前打开的数据库连接数
        /// </summary>
        public static int ConnectionCount
        {
            get
            {
                return _ConnectionCount;
            }
            private set
            {
                if (_ConnectionCount < value)
                {
                    int diff = (value - _ConnectionCount);
                    if (int.MaxValue - diff > _ConnectionTotalCount)
                        _ConnectionTotalCount += diff;
                }
                _ConnectionCount = value;
                if (_ConnectionCount > _ConnectionPeakCount)
                {
                    _ConnectionPeakCount = _ConnectionCount;
                }
            }
        }

        /// <summary>
        /// 到目前为止同时打开数据库连接的最大值
        /// </summary>
        public static int ConnectionPeakCount
        {
            get
            {
                return _ConnectionPeakCount;
            }
        }

        /// <summary>
        /// 到目前为止打开数据库的次数
        /// </summary>
        public static int ConnectionTotalCount
        {
            get
            {
                return _ConnectionTotalCount;
            }
        }

        private DbConnection _connection = null;
        private DbTransaction _transaction = null;

        public Executor(string connectionString)
        {
            if (_connection == null)
            {
                _connection = NewConnection();
                _connection.ConnectionString = connectionString;
                _connection.Open();
                ConnectionCount++;
            }
        }

        /// <summary>
        /// 启动一个事务
        /// </summary>
        public void BeginTransaction()
        {
            Debug.Assert(_transaction == null);
            _transaction = _connection.BeginTransaction();
        }

        public void BeginTransaction(IsolationLevel iso)
        {
            Debug.Assert(_transaction == null);
            _transaction = _connection.BeginTransaction(iso);
        }

        /// <summary>
        /// 提交当前事务
        /// </summary>
        public void CommitTransaction()
        {
            if (_transaction != null)
            {
                _transaction.Commit();
                _transaction.Dispose();
                _transaction = null;
            }
        }

        /// <summary>
        /// 回滚当前事务
        /// </summary>
        public void RollbackTransaction()
        {
            if (_transaction != null)
            {
                _transaction.Rollback();
                _transaction.Dispose();
                _transaction = null;
            }
        }

        /// <summary>
        /// 执行无条件无排序的查询
        /// </summary>
        /// <returns></returns>
        public DataList<T> Query<T>() where T : DataEntity, new()
        {
            return Query<T>(null, null);
        }

        /// <summary>
        /// 执行查询语句，并返回类型T
        /// </summary>
        /// <typeparam name="T">实体类型，必须是DataEntity的派生类</typeparam>
        /// <param name="sql">查询语句</param>
        /// <returns>实体类列表</returns>
        public DataList<T> Query<T>(string sql) where T : DataEntity, new()
        {
            if (sql == null || sql == "")
                throw new Exception("Query SQL statement is not provided.");

            // 执行查询，返回第一个表，如果查询没有返回表，则此查询语句不正确（可能不是查询）。
            DataSet ds = new DataSet();
            DbCommand cmd = NewCommand();
            cmd.Connection = _connection;
            cmd.Transaction = _transaction;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = sql;

            DbDataAdapter adp = NewDataAdapter();
            adp.SelectCommand = cmd;

            adp.Fill(ds);
            if (ds.Tables.Count > 0)
                return new DataList<T>(ds.Tables[0].DefaultView);
            else
                throw new Exception("The Query didn't return a table.");
        }

        public IDataReader ExecuteReader(string sql)
        {
            DbCommand cmd = NewCommand();
            cmd.Connection = _connection;
            cmd.Transaction = _transaction;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = sql;

            return cmd.ExecuteReader();
        }

        /// <summary>
        /// 执行一条非查询的SQL语句
        /// </summary>
        /// <param name="sql">非查询的SQL语句</param>
        /// <returns>受影响行数</returns>
        public virtual int Execute(string sql)
        {
            if (sql == null || sql == "")
                throw new Exception("SQL statement to be executed is not provided.");

            DbCommand cmd = NewCommand();
            cmd.Connection = _connection;
            cmd.Transaction = _transaction;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = sql;

            return cmd.ExecuteNonQuery();
        }

        /// <summary>
        /// 执行一条查询语句，并返回第一行记录的第一个字段值
        /// </summary>
        /// <param name="sql">查询语句</param>
        /// <returns>第一行记录的第一个字段值</returns>
        public virtual object ExecuteScalar(string sql)
        {
            if (sql == null || sql == "")
                throw new Exception("SQL statement to be executed is not provided.");

            DbCommand cmd = NewCommand();
            cmd.Connection = _connection;
            cmd.Transaction = _transaction;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = sql;
            return cmd.ExecuteScalar();
        }

        public virtual int Insert<T>(T entity, string sql)
        {
            return this.Execute(sql);
        }

        /// <summary>
        /// 插入一条记录
        /// </summary>
        /// <typeparam name="T">记录的实体类型</typeparam>
        /// <param name="t">实体类实例</param>
        /// <returns>受影响行数</returns>
        public virtual int Insert<T>(T t) where T : DataEntity, new()
        {
            Type type = typeof(T);
            object[] attrs = type.GetCustomAttributes(typeof(TableNameAttribute), false);
            if (attrs.Length == 0)
                throw new Exception("TableName attribute is not provided.");
            TableNameAttribute tname = attrs[0] as TableNameAttribute;

            return this.Insert(t as DataEntity, tname.Value);
        }

        /// <summary>
        /// 更新符合条件的记录行
        /// </summary>
        /// <typeparam name="T">记录的实体类型</typeparam>
        /// <param name="t">实体类实例</param>
        /// <param name="condition">更新筛选条件</param>
        /// <returns>受影响行数</returns>
        public virtual int Update<T>(T t, Condition condition) where T : DataEntity, new()
        {
            Type type = typeof(T);
            object[] attrs = type.GetCustomAttributes(typeof(TableNameAttribute), false);
            if (attrs.Length == 0)
                throw new Exception("TableName attribute is not provided.");
            TableNameAttribute tname = attrs[0] as TableNameAttribute;

            return this.Update(t as DataEntity, tname.Value, condition);
        }

        public virtual int Update<T>(T t, string sql)
        {
            return this.Execute(sql);
        }

        /// <summary>
        /// 删除符合条件的记录行
        /// </summary>
        /// <typeparam name="T">记录的实体类型</typeparam>
        /// <param name="condition">删除筛选条件</param>
        /// <returns>受影响行数</returns>
        public virtual int Delete<T>(Condition condition) where T : DataEntity, new()
        {
            Type type = typeof(T);
            object[] attrs = type.GetCustomAttributes(typeof(TableNameAttribute), false);
            if (attrs.Length == 0)
                throw new Exception("TableName attribute is not provided.");
            TableNameAttribute tname = attrs[0] as TableNameAttribute;

            return this.Delete(tname.Value, condition);
        }

        public virtual int Delete<T>(string sql)
        {
            return this.Execute(sql);
        }

        /// <summary>
        /// 实现IDisposable
        /// </summary>
        #region IDisposable Members

        public void Dispose()
        {
            if (_transaction == null)
            {
                if (_connection != null)
                {
                    _connection.Dispose();
                    ConnectionCount--;
                }
                _connection = null;
                GC.SuppressFinalize(this);
            }
        }

        #endregion IDisposable Members

        #region abstract members to be overrided

        /// <summary>
        /// 创建一个新的数据库连接，本方法用于类构造函数中，创建一个实例化的连接对象
        /// </summary>
        /// <returns>数据库连接类的实例</returns>
        protected abstract DbConnection NewConnection();

        /// <summary>
        /// 创建一个新的数据库数据适配器
        /// </summary>
        /// <returns></returns>
        protected abstract DbDataAdapter NewDataAdapter();

        /// <summary>
        /// 创建一个新的数据库命令对象
        /// </summary>
        /// <returns></returns>
        protected abstract DbCommand NewCommand();

        /// <summary>
        /// 按查询条件查询实体T，并按指定排序方式排序
        /// </summary>
        /// <typeparam name="T">实体类型，必须是DataEntity的派生类</typeparam>
        /// <param name="condition">查询条件</param>
        /// <param name="sortings">排序方式</param>
        /// <returns>实体类列表</returns>
        public abstract DataList<T> Query<T>(Condition condition, params Sort[] sortings) where T : DataEntity, new();

        /// <summary>
        /// 插入一条记录
        /// </summary>
        /// <param name="data">实体类实例</param>
        /// <param name="tableName">实体对应表名</param>
        /// <returns>受影响行数</returns>
        public abstract int Insert(DataEntity data, string tableName);

        /// <summary>
        /// 更新符合条件的记录行
        /// </summary>
        /// <param name="data">实体类实例</param>
        /// <param name="tableName">实体对应表名</param>
        /// <param name="condition">更新筛选条件</param>
        /// <returns>受影响行数</returns>
        public abstract int Update(DataEntity data, string tableName, Condition condition);

        /// <summary>
        /// 删除符合条件的记录行
        /// </summary>
        /// <param name="tableName">实体对应表名</param>
        /// <param name="condition">删除筛选条件</param>
        /// <returns>受影响行数</returns>
        public abstract int Delete(string tableName, Condition condition);

        #endregion abstract members to be overrided
    }
}
